package com.example.user.controller.code;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.example.framework.common.exception.ServiceException;
import com.example.framework.common.exception.enums.GlobalErrorCodeConstants;
import com.example.framework.common.pojo.R;
import com.example.framework.redis.core.util.RedisUtils;
import com.example.module.system.dal.redis.RedisKeyConstants;
import com.example.user.constants.ErrorCodeConstants;
import com.example.user.constants.SourceTypeEnum;
import com.example.user.controller.code.vo.CodeSendVO;
import com.example.user.controller.code.vo.CodeVerifyReqVo;
import com.example.user.service.code.CodeService;
import com.example.user.service.code.CodeServiceFactory;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.annotation.security.PermitAll;
import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Tag(name = "短信、邮箱验证码服务")
@RestController
@RequestMapping("/code")
public class CodeController {

    @Resource
    private CodeServiceFactory codeServiceFactory;

    @PermitAll
    @Operation(summary = "发送验证码")
    @PostMapping("/send")
    public R<?> sendCode(@Valid @RequestBody CodeSendVO reqVO) {
        checkParam(reqVO);
        CodeService codeService = codeServiceFactory.get(SourceTypeEnum.get(reqVO.getSource()));
        codeService.sendCode(reqVO);
        return R.success("验证码发送成功");
    }

    private void checkParam(CodeSendVO reqVo) {
        // 短信验证码才需要校验滑块验证码
        if (reqVo.getSource() == SourceTypeEnum.SMS.getType()) {
            if (StrUtil.isBlank(reqVo.getCaptchaId()) || StrUtil.isBlank(reqVo.getTicket())) {
                throw ServiceException.of(GlobalErrorCodeConstants.BAD_REQUEST.getCode(), "滑块验证码的id和ticket不能为空");
            }
            String ticketFromRedis = RedisUtils.getString(RedisKeyConstants.CAPTCHA_TICKET_PREFIX + reqVo.getCaptchaId());
            Assert.equals(ticketFromRedis, reqVo.getTicket(), () -> ServiceException.of(ErrorCodeConstants.CAPTCHA_CODE_EXPIRED));
        }
    }

    @PermitAll
    @Operation(summary = "校验验证码")
    @PostMapping("/verify")
    public R<Boolean> verifyCode(@Valid @RequestBody CodeVerifyReqVo reqVO) {
        CodeService codeService = codeServiceFactory.get(SourceTypeEnum.get(reqVO.getSource()));
        codeService.verifyCode(reqVO.getId(), reqVO.getCode(), false);
        return R.success(true);
    }

}
